package com.example.mq.mqserver.core;

import org.springframework.cglib.beans.FixedKeySet;

import java.beans.BeanInfo;

public class Router {

    /*
    bindingKey命名规则：
    1.数字，下划线，字母
    2.使用.进行分割
    3.允许*或#作为一部分或多部分
     */
    public static boolean checkBindingKey(String bindingKey) {
        //也是合法的情况，直接和扇出交换机用不到，所以可以设置为""
        if(bindingKey.length() == 0) {
            return true;
        }
        for (int i = 0; i < bindingKey.length(); i++) {
            if(bindingKey.charAt(i) >= 'A' && bindingKey.charAt(i) <= 'Z') {
                continue;
            }
            if(bindingKey.charAt(i) >= 'a' && bindingKey.charAt(i) <= 'z') {
                continue;
            }
            if(bindingKey.charAt(i) == '.' || bindingKey.charAt(i) == '_') {
                continue;
            }
            if(bindingKey.charAt(i) >= '0' && bindingKey.charAt(i) <= '9') {
                continue;
            }
            if(bindingKey.charAt(i) == '*' || bindingKey.charAt(i) == '#') {
                continue;
            }
            //除此之外其他情况都是返回不合法的
            return false;
        }
        //检查*和#是否为独立的部分
        //aaa.*.bbb合法，aaa.a*.bbb/aaa.*a.bbb/aaa.#a.bbb不合法
        String[] strs = bindingKey.split("\\.");
        for(String s : strs) {
            if(s.length() > 1 && (s.contains("*") || s.contains("#"))) {
                return false;
            }
        }
        //这里认为在进行约定一下
        //如果使用前三种的话，匹配起来就有点麻烦，同时功能性不大
        //a.#.*.b 不合法
        //a.#.#.b 不合法
        //a.*.#.b 不合法
        //a.*.*.b 合法
        for(int i = 0; i < strs.length-1; i++) {
            if(strs[i].equals("#") && strs[i+1].equals("*")) {
                return false;
            }
            if(strs[i].equals("*") && strs[i+1].equals("#")) {
                return false;
            }
            if(strs[i].equals("#") && strs[i+1].equals("#")) {
                return false;
            }
        }
        return true;
    }

    /*
    routingKey命名规则：
    1.数字。下划线，字母
    2.用.进行分割
     */
    public static boolean checkRoutingKey(String routingKey) {
        //进行判空，有些时候(扇出交换机用不到)不需要routingKey就可以设置为"",但是并不代表是错误的
        if(routingKey.length() == 0) {
            return true;
        }
        for (int i = 0; i < routingKey.length(); i++) {
            if(routingKey.charAt(i) >= 'A' && routingKey.charAt(i) <= 'Z') {
                continue;
            }
            if(routingKey.charAt(i) >= 'a' && routingKey.charAt(i) <= 'z') {
                continue;
            }
            if(routingKey.charAt(i) == '.' || routingKey.charAt(i) == '_') {
                continue;
            }
            if(routingKey.charAt(i) >= '0' && routingKey.charAt(i) <= '9') {
                continue;
            }
            if(routingKey.charAt(i) == '#' || routingKey.charAt(i) == '*') {
                continue;
            }
            //除此之外其他情况都是返回不合法的
            return false;
        }
        return true;
    }

    public static boolean route(ExchangeType type, Binding binding, BasicProperties basicProperties) {
        if(type == ExchangeType.FANOUT) {
            return true;
        }else if(type == ExchangeType.TOPIC) {
            return routeTopic(binding.getBindingKey(),basicProperties.getRoutingKey());
        }else {
            System.out.println("传入的交换机类型非发");
            return false;
        }
    }

    // [测试用例]
    // binding key          routing key         result
    // aaa                  aaa                 true
    // aaa.bbb              aaa.bbb             true
    // aaa.bbb              aaa.bbb.ccc         false
    // aaa.bbb              aaa.ccc             false
    // aaa.bbb.ccc          aaa.bbb.ccc         true
    // aaa.*                aaa.bbb             true
    // aaa.*.bbb            aaa.bbb.ccc         false
    // *.aaa.bbb            aaa.bbb             false
    // #                    aaa.bbb.ccc         true
    // aaa.#                aaa.bbb             true
    // aaa.#                aaa.bbb.ccc         true
    // aaa.#.ccc            aaa.ccc             true
    // aaa.#.ccc            aaa.bbb.ccc         true
    // aaa.#.ccc            aaa.aaa.bbb.ccc     true
    // #.ccc                ccc                 true
    // #.ccc                aaa.bbb.ccc         true
    public static boolean routeTopic(String bindingKey,String routingKey) {
        //进行routingKey和bindingKey的匹配
        //将bindingKey和routingKey进行分割（按照"."）
        String[] bindings = bindingKey.split("\\.");
        int bindLen = bindings.length;
        String[] routings = routingKey.split("\\.");
        int routeLen = routings.length;
        int i = 0;
        int j = 0;
        while(i < bindLen && j < routeLen) {
            if(bindings[i].equals("*")) {
                i++;
                j++;
                continue;
            }else if(bindings[i].equals("#")) {
                i++;
                if(i == bindLen) {
                    //已经到bindings末尾了，直接返回成功
                    return true;
                }
                System.out.println(i);
                //还没到末尾，需要去routings去找到bindings[i]，如果没找到此时两个key已然不相同
                int routingIndex = findRoutingIndex(bindings,routings,i,j);
                if(routingIndex == -1) {
                    //没找到
                    return false;
                }
                j = routingIndex;
            }else if(bindings[i].equals(routings[j])){
                //bindings[i]和routings[i]相同
                i++;
                j++;
                continue;
            }else {
                return false;
            }

        }
        if(i == bindLen && j == routeLen) {
            return true;
        }
        return false;

    }

    private static int findRoutingIndex(String[] bindings,String[] routings, int i, int j) {
        for(int k = j; k < routings.length; k++) {
            if(routings[k].equals(bindings[i])) {
                return k;
            }
        }
        return -1;
    }

}


